代理和反射的定义
调用 new Proxy() 可常见代替其它目标 (target) 对象的代理,它虚拟化了目标,所以二者看起来功能一致。
代理可拦截JS引擎内部目标的底层对象操作,这些底层操作被拦截后会触发响应特定操作的陷阱函数。
反射 API 以 Reflect 对象的形式出现,对象中方法的默认特性与相同的底层操作一致,而代理可以覆写这种操作,每一个代理陷阱对应一个命名和参数都相同的 Reflect 方法。
应用
基础用法
let target = {};
let p = new Proxy(target, {});
p.a = 37; // 操作转发到目标
console.log(target.a); // 37. 操作已经被正确地转发
get、set、has、deleteProperty的使用
- get() 方法用于拦截对象的读取属性操作
- set() 方法用于拦截设置属性值的操作
- has() 方法可以看作是针对 in 操作的钩子
- deleteProperty() 方法用于拦截对对象属性的 delete 操作
let target = {
name: 'target',
color: 'blue',
size: 50,
skill: 'drink'
}
let proxy = new Proxy(target, {
set: function(trapTarget, key, value, receiver) {
// 忽略不希望受到影响的已有属性
if(!trapTarget.hasOwnProperty(key)) {
if(isNaN(value)) {
throw new TypeError('属性必须是数字!')
}
}
//添加属性
return Reflect.set(trapTarget, key, value, receiver)
},
get: function(trapTarget, key, receiver) {
if(!(key in receiver)) {
throw new TypeError(key + '属性不存在!')
}
return Reflect.get(trapTarget, key, receiver)
},
has: function(trapTarget, key) {
if(key === 'color') {
return false
}else {
return Reflect.has(trapTarget, key)
}
},
deleteProperty: function(trapTarget, key) {
if(key === 'skill') {
return false
}else {
return Reflect.deleteProperty(trapTarget, key)
}
}
});
//添加一个新属性
proxy.count = 1
console.log(target.count) //1
proxy.name = 'proxy'
console.log(proxy.name) //proxy
console.log(target.name) //proxy
proxy.anotherName = 'proxy' //抛出错误: 属性必须是数字!
console.log(proxy.age) //抛出错误:age属性不存在!
console.log('name' in proxy) //true
console.log('color' in proxy) //false
console.log('size' in proxy) //true
let result1 = delete proxy.size
console.log('size' in proxy) //false
console.log('skill' in proxy) //true
let result2 = delete proxy.skill
console.log('skill' in proxy) //true
参考
《深入理解ES6》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。